package com.easyUploader.entity.vo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.exception.CustomException;
import com.common.util.StringUtil;
import com.easyUploader.entity.dao.Bucket;
import com.easyUploader.entity.dao.FileChunk;
import com.easyUploader.entity.dao.FileStorage;
import com.easyUploader.property.LocalFileProperty;
import com.easyUploader.service.IBucketService;
import com.easyUploader.service.IFileChunkService;
import com.easyUploader.service.IFileStorageService;
import com.easyUploader.service.impl.FileChunkServiceImpl;
import com.easyUploader.threadHolder.FileInfoThreadHolder;
import com.easyUploader.threadHolder.UserThreadHolder;
import com.easyUploader.util.FileUtil;
import com.easyUploader.util.PathUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import static com.easyUploader.entity.pojo.BucketStatus.BUCKET_STATUS_READ_WRITE;

/**
 * @author 大忽悠
 * @create 2022/10/29 21:26
 */
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class FileChunkVo {
    /**
     * 文件名
     */
    @ApiModelProperty("文件名")
    private String fileName;

    /**
     * 目录路径
     */
    @ApiModelProperty("目录路径")
    private String directoryPath;

    /**
     * 桶名
     */
    @ApiModelProperty("桶名")
    private String bucketName;

    /**
     * 当前分片标号,从1开始
     */
    @ApiModelProperty("当前分片标号,从1开始")
    private Integer chunkNumber;

    /**
     * 当前分片大小
     */
    @ApiModelProperty("当前分片大小")
    private Float chunkSize;

    /**
     * 当前分片内实际装载数据大小
     */
    @ApiModelProperty("当前分片内实际装载数据大小")
    private Float dataSize;

    /**
     * 分片关联文件的总大小
     */
    @ApiModelProperty("分片关联文件的总大小")
    private Float totalSize;

    /**
     * 总分片数
     */
    @ApiModelProperty("总分片数")
    private Integer totalChunk;

    /**
     * 当前文件对应的md5校验码
     */
    @ApiModelProperty("当前文件对应的md5校验码")
    private String fileIdentifier;

    /**
     * 当前分片对应的md5校验码
     */
    @ApiModelProperty("当前分片对应的md5校验码")
    private String chunkIdentifier;

    /**
     * 上传分片的用户id
     */
    @ApiModelProperty("上传分片的用户id")
    private Integer uploadBy;

    /**
     * 当前分片对应的数据载体
     */
    @ApiModelProperty("当前分片对应的数据载体")
    private MultipartFile file;



    /**
     * 当前文件的分片是否已经上传 <br>
     * 暂时不考虑其他用户已经上传同样分片内容的情况,因为不方便处理
     */
    public Boolean checkChunkUpLoad(IFileChunkService fileChunkService) {
        return fileChunkService.count(new QueryWrapper<FileChunk>().eq("chunk_identifier",chunkIdentifier)
                .eq("file_identifier",fileIdentifier).eq("upload_by",uploadBy))!=0;
    }

    public void safeCheck(IBucketService iBucketService) {
        if (null == file) {
            throw new CustomException("文件数据丢失","请把分片数据携带着谢谢您嘞!");
        }
        //判断存储桶是否存在,如果不存在抛出异常,并且当前存储桶必须是可读写的
        bucketCheck(iBucketService);
    }

    /**
     * 目前存储桶访问权限只支持公开状态<br>
     * TODO: 如果存储桶是私有的话,用户上传文件需要进行验证,这里待完善
     */
    private void bucketCheck(IBucketService iBucketService) {
        Bucket bucket = iBucketService.getOne(new QueryWrapper<Bucket>().eq("name", bucketName)
                .eq("create_by", UserThreadHolder.get().getId()));

        Assert.notNull(bucket,"无法找到名为"+bucketName+"的存储桶!");
        Assert.isTrue(bucket.getBucketType().equals(BUCKET_STATUS_READ_WRITE),"当前存储桶为只读状态");

        //设置当前操作桶信息进线程上下文中保存
        FileInfoThreadHolder.setBucketId(bucket.getId());
        FileInfoThreadHolder.setBucketName(bucketName);
    }


    /**
     * 当前文件关联的分片是否全部到位
     */
    public boolean allChunkReady(FileChunkServiceImpl fileChunkService) {
        long chunkCount = fileChunkService.count(new QueryWrapper<FileChunk>().eq("file_identifier", fileIdentifier));
        return totalChunk ==Math.toIntExact(chunkCount);
    }

    public String getWrappedFilePath(LocalFileProperty localFileProperty) {
        //构建完整的路径: baseDir+空间+用户家目录+bucketName+dirPath+fileName
        String wrappedFullFilePath = localFileProperty.getFileSavePath(this);
        //如果父目录不存在,则进行创建
        FileUtil.createDirIfNotExist(wrappedFullFilePath,true);
        log.info("当前上传文件包装后的完整路径为: {}",wrappedFullFilePath);
        return wrappedFullFilePath;
    }

    public void setDirectoryPath(String directoryPath) {
        this.directoryPath = PathUtil.modifyPathByOs(directoryPath);
    }

    public String getFileName() {
        //检查文件名是否设置
        if(StringUtil.isNullOrEmpty(fileName)){
            fileName=file.getOriginalFilename();
        }
        return fileName;
    }
}
